﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PIT.Labs.ProjectRepository.Owl2DotNet.Xsd
{
    class XsdOntology : XsdEntityBase, IOntology
    {
        internal Dictionary<string, XsdClass> classes;
        internal Dictionary<string, XsdDataType> datatypes;
        internal Dictionary<string, XsdDataProperty> dataProperties;
        internal Dictionary<string, XsdObjectProperty> objectProperties;
        internal Dictionary<string, XsdIndividual> individuals;

        public XsdOntology(string name)
            : base(null, name)
        {
            classes = new Dictionary<string, XsdClass>();
            dataProperties = new Dictionary<string, XsdDataProperty>();
            objectProperties = new Dictionary<string, XsdObjectProperty>();
            individuals = new Dictionary<string, XsdIndividual>();
            datatypes = new Dictionary<string, XsdDataType>();
            ontology = this;
        }

        internal void Insert(XsdClass c)
        {
            string uri = c.Uri.OriginalString;
            if (!classes.ContainsKey(uri))
            {
                classes.Add(uri, c);
            }
        }

        internal void Insert(XsdDataProperty c)
        {
            string uri = c.Uri.OriginalString;
            if (!dataProperties.ContainsKey(uri))
            {
                dataProperties.Add(uri, c);
            }
        }

        internal void Insert(XsdObjectProperty c)
        {
            string uri = c.Uri.OriginalString;
            if (!objectProperties.ContainsKey(uri))
            {
                objectProperties.Add(uri, c);
            }
        }

        internal void Insert(XsdIndividual c)
        {
            string uri = c.Uri.OriginalString;
            if (!individuals.ContainsKey(uri))
            {
                individuals.Add(uri, c);
            }
        }
        
        internal void Insert(XsdDataType c)
        {
            string uri = c.Uri.OriginalString;
            if (!datatypes.ContainsKey(uri))
            {
                datatypes.Add(uri, c);
            }
        }

        private static T GetOrNull<T>(Dictionary<string, T> d, Uri u){
            T r = default(T);
            if (d.ContainsKey(u.OriginalString))
            {
                r = d[u.OriginalString];
            }
            return r;
        }

        public IClass Thing
        {
            get { throw new NotImplementedException(); }
        }

        public IEnumerable<IClass> Classes
        {
            get { throw new NotImplementedException(); }
        }

        public IClass GetClass(Uri uri)
        {
            return GetXsdClass(uri);
        }

        internal XsdClass GetXsdClass(Uri uri)
        {
            return GetOrNull(classes, uri);
        }

        public IEnumerable<IAnnotationProperty> AnnotationProperties
        {
            get { throw new NotImplementedException(); }
        }

        public IAnnotationProperty GetAnnotationProperty(Uri uri)
        {
            throw new NotImplementedException();
        }

        public IEnumerable<IDataProperty> DataProperties
        {
            get { return dataProperties.Select(x => (IDataProperty)x.Value); }
        }

        public IDataProperty GetDataProperty(Uri uri)
        {
            return GetXsdDataProperty(uri);
        }

        internal XsdDataProperty GetXsdDataProperty(Uri uri)
        {
            return GetOrNull(dataProperties, uri);
        }

        public IEnumerable<IDataType> DataTypes
        {
            get { throw new NotImplementedException(); }
        }

        public IDataType GetDataType(Uri uri)
        {
            throw new NotImplementedException();
        }

        public IEnumerable<IIndividual> Individuals
        {
            get { throw new NotImplementedException(); }
        }

        public IIndividual GetIndividual(Uri uri)
        {
            return GetXsdIndividual(uri);
        }

        internal XsdIndividual GetXsdIndividual(Uri uri)
        {
            return GetOrNull(individuals, uri);
        }

        public IEnumerable<IObjectProperty> ObjectProperties
        {
            get { throw new NotImplementedException(); }
        }

        public IObjectProperty GetObjectProperty(Uri uri)
        {
            return GetXsdObjectProperty(uri);
        }

        internal XsdObjectProperty GetXsdObjectProperty(Uri uri)
        {
            return GetOrNull(objectProperties, uri);
        }
    }
}
